package com.fractalist.base.core.utils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Locale;
import java.util.Random;

public class DateUtils {

	/** 日期格式化--包含具体时间** */
	private static HashMap<String, SimpleDateFormat> dateFormatMap = new HashMap<String, SimpleDateFormat>();

	private static Calendar calendar = Calendar.getInstance();

	public static final String YEAR = "YYYY";
	public static final String MM = "MM";
	public static final String DD = "DD";
	public static final String HH = "HH";
	public static final String MI = "MI";
	public static final String SS = "SS";
	public static final String TIME_TYPE_TIME = "HH:mm:ss";
	public static final String TIME_TYPE_DAY = "yyyy-MM-dd";
	public static final String TIME_TYPE_DAY_2 = "yyyy.M.d";
	public static final String TIME_TYPE_SIMPLE = "yyyy-MM-dd HH:mm:ss";

	// DateUtils添加进来的
	public static SimpleDateFormat dateTimeFormatter = new SimpleDateFormat(
			"yyyy-MM-dd HH:mm:ss");
	public static SimpleDateFormat dateFormatter = new SimpleDateFormat(
			"yyyy-MM-dd");

	// private static Logger logger = Logger
	// .getLogger(SysConstants.LOG_LOGIC_FILE_TARGET_NAME);

	public static Date DEFAULT_DATE = new Date(0);

	static {
		// 设置一星期的第一天是星期一
		calendar.setFirstDayOfWeek(Calendar.MONDAY);
	}

	/**
	 * 获取当前日期
	 * 
	 * @return
	 */
	public static String getCurDate() {
		SimpleDateFormat myFormatter = new SimpleDateFormat(TIME_TYPE_SIMPLE);
		Calendar curDate = Calendar.getInstance();
		return myFormatter.format(curDate.getTime());
	}

	public static String getfDate() {
		SimpleDateFormat myFormatter = new SimpleDateFormat("MM月dd日 HH:mm");
		Calendar curDate = Calendar.getInstance();
		return myFormatter.format(curDate.getTime());
	}

	public static String getFileNameByTime() {
		SimpleDateFormat dateTimeFormatter = new SimpleDateFormat(
				"yyyyMMddHHmmss");
		Calendar curDate = Calendar.getInstance();
		Random random = new Random(1000);
		return dateTimeFormatter.format(curDate.getTime()) + "_"
				+ System.currentTimeMillis();
	}

	public static String getPositionId() {
		SimpleDateFormat dateTimeFormatter = new SimpleDateFormat(
				"yyyyMMddHHmmss");
		Calendar curDate = Calendar.getInstance();
		return dateTimeFormatter.format(curDate.getTime());
	}

	/**
	 * 把给定日期与给定月数进行运算,月数可以是负数.返回给定日期与给定日期的差或和
	 * 
	 * @param as_date
	 *            :格式是yyyymm的日期,现支持yyyy-mm-dd型日期
	 * @param months
	 * @return
	 * @throws Exception
	 */
	public static String getDateNMonths(String dateStr, int months) {
		SimpleDateFormat sdf = new SimpleDateFormat(TIME_TYPE_DAY);
		java.util.Date date=null;
		try {
			date = sdf.parse(dateStr);
		} catch (ParseException e1) {
			e1.printStackTrace();
		}
		
		if (months == 0) { // 月数为零,直接返回给定日期
			return dateStr;
		}
		if (months > 1200 || months < -1200) { // 日期限制在100年以内
			System.out.println("请把日期限制在100年内");
			return null;
		}
		GregorianCalendar gc = new GregorianCalendar();
		gc.setTime(date);
		gc.add(Calendar.MONTH, months);
		java.util.Date date2 = gc.getTime();
		String retStrDate="";
		try {
			retStrDate=parseDateToString(date2,TIME_TYPE_DAY);
		} catch (Exception e) {
			retStrDate="";
		}
		String year=retStrDate.split("-")[0];
		String moth=retStrDate.split("-")[1];
		String day=retStrDate.split("-")[2];
		
		retStrDate=year+"-"+moth+"-"+getMonthLastDay(Integer.parseInt(year),Integer.parseInt(moth));
		
		return retStrDate;
	}

	/**
	* 得到指定月的天数
	* */
	public static int getMonthLastDay(int year, int month){
		Calendar a = Calendar.getInstance();
		a.set(Calendar.YEAR, year);
		a.set(Calendar.MONTH, month - 1);
		a.set(Calendar.DATE, 1);//把日期设置为当月第一天
		a.roll(Calendar.DATE, -1);//日期回滚一天，也就是最后一天
		int maxDate = a.get(Calendar.DATE);
		return maxDate;
	}
	
	/**
	 * @功能描述:格式化字符类型的日期时间
	 * @param dateStr
	 * @return
	 */
	public static String getDateFormatByDateStr(String dateStr) {
		String forMatStr = "yyyy-MM-dd HH:mm:ss";

		if (dateStr.indexOf(".") != -1) {
			forMatStr = forMatStr.replaceAll("-", ".");
		} else if (dateStr.indexOf("/") != -1) {
			forMatStr = forMatStr.replaceAll("-", "/");
		} else if (dateStr.indexOf("-") == -1) {
			forMatStr = forMatStr.replaceAll("-", "");
		}

		forMatStr = forMatStr.substring(0, dateStr.length());

		return forMatStr;
	}

	/**
	 * @功能描述:格式化字符类型的日期时间
	 * @param dateStr
	 * @return
	 */
	public static String getDateFormatByDateStr(String dateStr, String fromat) {
		SimpleDateFormat myFormatter = new SimpleDateFormat(fromat);
		String ret = "";
		try {
			ret = myFormatter.format(myFormatter.parse(dateStr));
		} catch (ParseException e) {
		}
		return ret;
	}

	public static boolean isdateValidadte(Date std, String cd, int days) {
		Date dd = DateUtils.parseStringToDate(cd, "yyyyMMdd");
		long a = std.getTime();
		long b = dd.getTime();

		long intD = (a - b) / (1000 * 60 * 60 * 24);
		if (intD >= 0 && intD <= days) {
			return true;
		}

		return false;
	}

	/**
	 * @功能描述:
	 * @param userFormat
	 * @return
	 * @author sam
	 */
	public static SimpleDateFormat getUserFormat(String userFormat)
			throws Exception {
		try {
			synchronized (dateFormatMap) {
				if (!dateFormatMap.containsKey(userFormat)) {
					SimpleDateFormat simpleFormat = new SimpleDateFormat(
							userFormat);
					dateFormatMap.put(userFormat, simpleFormat);
				}
			}
		} catch (Exception e) {
			System.out.println(e);
		}
		return (SimpleDateFormat) dateFormatMap.get(userFormat).clone();
	}

	/**
	 * @功能描述:将日期转换为字符串--
	 * @param date
	 * @return
	 * @author sam
	 */
	public static String parseDateToString(Date date, String formatStirng)
			throws Exception {
		if (null == date)
			return "";
		else {
			String format = formatStirng;
			Locale locale = new Locale("en", "US");
			SimpleDateFormat formatter = new SimpleDateFormat(format.trim(),
					locale);
			return formatter.format(date);
		}
	}

	public static String parseDateToStringx(String date, String formatStirng)
			throws Exception {
		if (null == date)
			return "";
		else {
			SimpleDateFormat myFormatter = new SimpleDateFormat(
					"yyyy-MM-dd HH:mm:ss");
			Date startDate = null;
			try {
				startDate = myFormatter.parse(date);
			} catch (ParseException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			return getUserFormat(formatStirng).format(startDate);
		}
	}

	/**
	 * @功能描述:将字符串按照指定的格式转为日期
	 * @param String
	 *            dateStr 字符串日期
	 * @param String
	 *            formatString 日期格式
	 * @return
	 * @author sam
	 */
	public static Date parseStringToDate(String dateStr, String formatStirng) {
		try {
			return getUserFormat(formatStirng).parse(dateStr);
		} catch (Exception ex) {
			return DEFAULT_DATE;
		}
	}

	/**
	 * @功能描述:将字符串转换为日期
	 * @param dateStr
	 * @return
	 * @author sam
	 */
	public static Date parseStringToDate(String dateStr) {
		if (isNull(dateStr) || dateStr.length() < 4) {
			return DEFAULT_DATE;
		}
		String dateFormat = null;
		SimpleDateFormat sd = null;
		try {
			dateFormat = getDateFormatByDateStr(dateStr);
			sd = getUserFormat(dateFormat);
			return sd.parse(dateStr);
		} catch (Exception ex) {
			return DEFAULT_DATE;
		}
	}

	/**
	 * @功能描述:获取当前时间
	 * @return
	 * @author sam
	 */
	public static Date getCurrentDate() throws Exception {
		Date currTime = new Date(System.currentTimeMillis());
		return currTime;
	}

	/**
	 * @功能描述:检查执行区间
	 * @param curr
	 *            当前
	 * @param execute
	 *            执行时间
	 * @param delay
	 *            延迟时间
	 * @return
	 * @author sam
	 */
	public static boolean detecteTimeValidate(Date currTime, Date standTime,
			long delay) {
		long compareM = currTime.getTime();
		long refM = standTime.getTime();
		return compareM > (refM - delay) && compareM < (refM + delay);
	}

	/**
	 * @功能描述:检查指定时间是否在 指定的时间区间内
	 * @param compareTime
	 * @param beginTime
	 * @param endTime
	 * @return
	 * @author sam
	 */
	public static boolean detecteTimeInRange(Date currTime, Date beginTime,
			Date endTime) {
		long currM = currTime.getTime();
		long beginM = beginTime.getTime();
		long endM = endTime.getTime();
		return currM > beginM && currM < endM;
	}

	/**
	 * @功能描述:判断当前时间是否在指定时间 的指定间隔轮训内
	 * @param compareTime
	 * @param beginTime
	 * @param intervalNum
	 * @return
	 * @author sam
	 */
	public static boolean detecteTimeIntervalUnit(Date currTime,
			Date beginTime, int intervalNum) {
		Calendar cal = ((Calendar) calendar.clone());
		cal.setTime(currTime);
		int cDayOfYear = cal.get(Calendar.DAY_OF_YEAR);
		cal.setTime(beginTime);
		int bDayOfYear = cal.get(Calendar.DAY_OF_YEAR);

		if (((cDayOfYear - bDayOfYear) % intervalNum) == 0) {
			return true;
		}
		return false;
	}

	/**
	 * @功能描述:判断当前时间是否在指定时间 的指定间隔轮训内
	 * @param compareTime
	 * @param beginTime
	 * @param intervalNum
	 * @return
	 * @author sam
	 */
	public static boolean detecteWeekIntervalUnit(Date beginDate, Date endDate,
			int weekDay, int intervalNum) {
		Calendar cal = ((Calendar) calendar.clone());
		cal.setTime(endDate);
		int eDayOfWeek = cal.get(Calendar.DAY_OF_WEEK);

		if (weekDay != eDayOfWeek) {
			return false;
		}

		int times = getTimesOfWeekDay(beginDate, endDate, weekDay);
		if (times % intervalNum == 0) {
			return true;
		}
		return false;
	}

	/**
	 * @功能描述:判断从指定时间开始经历多少个指定的周几？ 
	 *                            計算指定時間段包含多少個指定的星期--规则如下，计算开始日期为一年中的第几个星期，结束时间为一年中的第几个星期
	 *                            ，差值 + 1 - 开始时间是否已经过指定星期 -结束时间是否没过指定星期
	 * @param compareTime
	 * @param beginTime
	 * @param intervalNum
	 * @return
	 * @author sam
	 */
	public static int getTimesOfWeekDay(Date beginDate, Date endDate,
			int weekDay) {
		Calendar cal = ((Calendar) calendar.clone());
		cal.setTime(beginDate);

		int bWeekOfYear = cal.get(Calendar.WEEK_OF_YEAR);
		int bDayOfWeek = cal.get(Calendar.DAY_OF_WEEK);

		cal.setTime(endDate);

		int eWweekOfYear = cal.get(Calendar.WEEK_OF_YEAR);
		int eDayOfWeek = cal.get(Calendar.DAY_OF_WEEK);

		return (eWweekOfYear - bWeekOfYear) + 1
				- (bDayOfWeek > weekDay ? 1 : 0)
				- (eDayOfWeek < weekDay ? 1 : 0);
	}

	/**
	 * @功能描述:判断从指定时间开始经历多少个指定的周几？ 
	 *                            計算指定時間段包含多少個指定的星期--规则如下，计算开始日期为一年中的第几个星期，结束时间为一年中的第几个星期
	 *                            ，差值 + 1 - 开始时间是否已经过指定星期 -结束时间是否没过指定星期
	 * @param compareTime
	 * @param beginTime
	 * @param intervalNum
	 * @return
	 * @author sam
	 */
	public static int getTimesOfMonthDay(Date beginDate, Date endDate,
			int monthDay) {
		Calendar cal = ((Calendar) calendar.clone());
		cal.setTime(beginDate);

		int bMonthOfYear = cal.get(Calendar.MONTH);
		int bDayOfMonth = cal.get(Calendar.DAY_OF_MONTH);

		cal.setTime(endDate);

		int eMonthOfYear = cal.get(Calendar.MONTH);
		int eDayOfMonth = cal.get(Calendar.DAY_OF_MONTH);

		return (eMonthOfYear - bMonthOfYear) + 1
				- (bDayOfMonth > monthDay ? 1 : 0)
				- (eDayOfMonth < monthDay ? 1 : 0);
	}

	/**
	 * @功能描述:判断当前时间是否在指定时间 的指定间隔轮训内
	 * @param compareTime
	 * @param beginTime
	 * @param intervalNum
	 * @return
	 * @author sam
	 */
	public static boolean detecteMonthDayIntervalUnit(Date beginDate,
			Date endDate, int monthDay, int intervalNum) {
		Calendar cal = ((Calendar) calendar.clone());
		cal.setTime(endDate);
		int eDayOfMonth = cal.get(Calendar.DAY_OF_MONTH);

		if (monthDay != eDayOfMonth) {
			return false;
		}

		int times = getTimesOfMonthDay(beginDate, endDate, monthDay);
		if (times % intervalNum == 0) {
			return true;
		}
		return false;
	}

	/**
	 * @功能描述:
	 * @param beginDate
	 * @param endDate
	 * @param daySeq
	 * @param weekDay
	 * @return
	 * @author sam
	 */
	public static int getTimesOfWeekMonth(Date beginDate, Date endDate,
			int weekSeq, int weekDay) {
		Calendar cal = ((Calendar) calendar.clone());
		cal.setTime(beginDate);
		int fromMonth = cal.get(Calendar.MONTH);
		int from_week_of_month = cal.get(Calendar.WEEK_OF_MONTH);
		int from_day_of_week = cal.get(Calendar.DAY_OF_WEEK);
		cal.setTime(endDate);

		int currMonth = cal.get(Calendar.MONTH);
		int curr_week_of_month = cal.get(Calendar.WEEK_OF_MONTH);
		int curr_day_of_week = cal.get(Calendar.DAY_OF_WEEK);

		return (currMonth - fromMonth)
				+ 1
				- ((from_week_of_month > weekSeq || (from_week_of_month == weekSeq && from_day_of_week > weekDay)) ? 1
						: 0)
				- ((curr_week_of_month < weekSeq || (curr_week_of_month == weekSeq && curr_day_of_week < weekDay)) ? 1
						: 0);
	}

	/**
	 * @功能描述:判断当前时间是否在指定时间 的指定间隔轮训内
	 * @param compareTime
	 * @param beginTime
	 * @param intervalNum
	 * @return
	 * @author sam
	 */
	public static boolean detecteMonthWeekDayIntervalUnit(Date beginDate,
			Date endDate, int weekSeq, int weekDay, int intervalNum) {
		Calendar cal = ((Calendar) calendar.clone());
		cal.setTime(endDate);
		int eWeekOfMonth = cal.get(Calendar.WEEK_OF_MONTH);
		int eDayOfWeek = cal.get(Calendar.DAY_OF_WEEK);

		if (weekSeq != eWeekOfMonth || weekDay != eDayOfWeek) {
			return false;
		}

		int times = getTimesOfWeekMonth(beginDate, endDate, weekSeq, weekDay);
		if (times % intervalNum == 0) {
			return true;
		}
		return false;
	}

	/**
	 * @功能描述:判断当前时间是否在指定时间 的指定间隔轮训内
	 * @param compareTime
	 * @param beginTime
	 * @param intervalNum
	 * @return
	 * @author sam
	 */
	public static boolean detecteHourIntervalUnit(Date standardTime,
			Date currTime, int intervalNum, long delayTime) {
		long sH = standardTime.getTime();
		long cH = currTime.getTime();

		int difH = Math.round((cH - sH) / (60 * 60 * 1000) - 0.5f);
		if (difH % intervalNum != 0) {
			return false;
		}

		long sdH = sH + difH * (60 * 60 * 1000);
		if (cH > sdH - delayTime && cH < sdH + delayTime) {
			return true;
		}
		return false;
	}

	/**
	 * @功能描述:判断当前时间是否在指定时间 的指定间隔轮训内
	 * @param compareTime
	 * @param beginTime
	 * @param intervalNum
	 * @return
	 * @author sam
	 */
	public static boolean detecteMinuteIntervalUnit(Date standardTime,
			Date currTime, int intervalNum, long delayTime) {
		long sM = standardTime.getTime();
		long cM = currTime.getTime();

		int difM = Math.round((cM - sM) / (60 * 1000) - 0.5f);
		if (difM % intervalNum != 0) {
			return false;
		}

		long sdM = sM + difM * 86400;
		if (cM > sdM - delayTime && cM < sdM + delayTime) {
			return true;
		}
		return false;
	}

	/**
	 * @功能描述:判断字符串是否为空
	 * @param str
	 * @return
	 * @author sam
	 */
	public static boolean isNull(Object str) {
		if (null == str || "".equals(str.toString())) {
			return true;
		}
		return false;
	}

	public static String appsf(String str) {
		if (null == str || str.length() <= 0) {
			return "";
		}
		SimpleDateFormat myFormatter = new SimpleDateFormat(
				"yyyy-MM-dd HH:mm:ss");
		Date startDate = null;
		try {
			startDate = myFormatter.parse(str);
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		SimpleDateFormat f = new SimpleDateFormat("MM月dd日 HH:mm");
		return f.format(startDate);
	}

	/**
	 * 使用参数Format格式化Date成字符串
	 */
	public static String format(Date date, String pattern) {
		String returnValue = "";

		if (date != null) {
			SimpleDateFormat df = new SimpleDateFormat(pattern);
			returnValue = df.format(date);
		}
		return (returnValue);
	}

	/**
	 * 格式化传进去的日期 格式：yyyy-MM-dd HH:mm:ss
	 * 
	 * @param date
	 * @return String
	 */
	public static String dateTimeFormatter(Date date) {
		if (date != null) {
			return dateTimeFormatter.format(date);
		} else {
			return dateTimeFormatter.format(new Date());
		}
	}

	/**
	 * 返回当前的日期字符串 格式： "yy-MM-dd"
	 * 
	 * @return
	 */
	public static String getCurrenDate() {
		String date = dateFormatter.format(new Date());
		return date;
	}

	/**
	 * 计算出strDate之后days天后的日期字符串 days可以为负数
	 * 
	 * @param strDate
	 * @param days
	 * @return
	 */
	public static final String addDayToString(String strDate, int days) {
		Calendar cale = toCalendar(strDate);
		cale.add(Calendar.DAY_OF_YEAR, days);
		return dateFormatterByPattern(cale.getTime(), "yyyy-MM-dd HH:mm:ss");
	}

	/**
	 * 把一个日期字符串转换成Calendar形式
	 * 
	 * @param strDate
	 * @return
	 */
	private static final Calendar toCalendar(String strDate) {
		Calendar cale = null;
		try {
			Date thisDate = dateTimeFormatter.parse(strDate);
			cale = Calendar.getInstance();
			cale.setTime(thisDate);
		} catch (Exception e) {
			return null;
		}
		return cale;
	}

	/**
	 * 减去指定天
	 * 
	 * @param strDate
	 * @param day
	 * @return
	 * @throws ParseException
	 */
	public static String subDay(String strDate, int day) throws ParseException {
		// SimpleDateFormat myFormatter = new SimpleDateFormat("yyyy-MM-dd");
		// Calendar lastDate = Calendar.getInstance();
		// lastDate.add(Calendar.DATE, -day);
		SimpleDateFormat myFormatter = new SimpleDateFormat("yyyy-MM-dd");
		Date startDate = myFormatter.parse(strDate);
		Calendar dateCal = Calendar.getInstance();
		dateCal.setTime(startDate);
		dateCal.add(Calendar.DATE, -day);
		return myFormatter.format(dateCal.getTime());
	}

	/**
	 * 根据所传的格式，格式化想要处理的date 格式： pattern 如果date ＝＝ null，则返回当前的date字符串
	 * 
	 * @param date
	 *            java.util.Date
	 * @return short format datetime
	 */
	public static String dateFormatterByPattern(Date date, String pattern) {
		SimpleDateFormat sdf = new SimpleDateFormat(pattern);
		if (date != null) {
			return sdf.format(date);
		} else {
			return sdf.format(new Date());
		}
	}

	/**
	 * 把传进去的字符串按照相对应的格式转换成日期，时间 格式: "yyyy-MM-dd HH:mm:ss"
	 * 
	 * @param param
	 * 
	 * @return java.util.Date
	 */
	public static Date dateTimeParser(String param) {
		Date date = null;
		try {
			date = dateTimeFormatter.parse(param);
		} catch (ParseException ex) {
		}
		return date;
	}

	/**
	 * 格式化传进去的日期 格式 ：yyyy-MM-dd
	 * 
	 * @param date
	 * @return
	 */
	public static String dateFormatter(Date date) {
		if (date != null) {
			return dateFormatter.format(date);
		} else {
			return dateFormatter.format(new Date());
		}
	}

	public static void main(String args[]) {

		Random random = new Random(1000);

		try {
			// DateUtil.getUserFormat("yyyyMMdd").toPattern();
			// System.out.println(DateUtil.getUserFormat("yyyy-MM-dd").toPattern());
			// date0 =
			// DateUtil.parseStringToDate(jobData.get(emt.getAttribute("dateField")),
			// "yyyyMMdd");
			// System.out.println(DateUtils
			// .parseStringToDate("2006/10/21 10:10:10"));
			// Date appDate = DateUtil.parseStringToDate("20080325",
			// "yyyyMMdd");
			// System.out.println(appDate.getTime());
			// Date birthDate = DateUtil.parseStringToDate("19811028",
			// "yyyyMMdd");
			//
			// System.out.println(Math.floor((appDate.getTime() -
			// birthDate.getTime()) / (24 * 3600 * 1000 * 365L)));
			System.out.println(DateUtils.getDateNMonths("2013-8-2",1));
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
